/** software/vulnerabilities/:cve */

import React, { useCallback, useContext } from "react";
import { useQuery } from "react-query";
import { useErrorHandler } from "react-error-boundary";
import { RouteComponentProps } from "react-router";
import { AxiosError } from "axios";

import useTeamIdParam from "hooks/useTeamIdParam";

import { AppContext } from "context/app";

import softwareVulnAPI, {
  IGetVulnerabilityQueryKey,
  IVulnerabilityResponse,
} from "services/entities/vulnerabilities";
import { ignoreAxiosError } from "interfaces/errors";

import { DEFAULT_USE_QUERY_OPTIONS } from "utilities/constants";

import Spinner from "components/Spinner";
import MainContent from "components/MainContent";
import TeamsHeader from "components/TeamsHeader";

import SoftwareVulnSummary from "./SoftwareVulnSummary/SoftwareVulnSummary";
import SoftwareVulnOSVersions from "./SoftwareVulnOSVersions";
import SoftwareVulnSoftwareVersions from "./SoftwareVulnSoftwareVersions";
import DetailsNoHosts from "../components/cards/DetailsNoHosts";

const baseClass = "software-vulnerability-details-page";

interface ISoftwareVulnerabilityDetailsRouteParams {
  cve: string;
  team_id?: string;
}

type ISoftwareVulnerabilityDetailsPageProps = RouteComponentProps<
  undefined,
  ISoftwareVulnerabilityDetailsRouteParams
>;

const SoftwareVulnerabilityDetailsPage = ({
  router,
  routeParams,
  location,
}: ISoftwareVulnerabilityDetailsPageProps) => {
  const { isPremiumTier, isOnGlobalTeam, config } = useContext(AppContext);
  const handlePageError = useErrorHandler();

  const {
    currentTeamId,
    teamIdForApi,
    userTeams,
    handleTeamChange,
  } = useTeamIdParam({
    location,
    router,
    includeAllTeams: true,
    includeNoTeam: true,
  });

  const {
    data: vuln,
    isLoading: isVulnLoading,
    isError: isVulnError,
  } = useQuery<
    IVulnerabilityResponse,
    AxiosError,
    IVulnerabilityResponse,
    IGetVulnerabilityQueryKey[]
  >(
    [
      {
        scope: "softwareVulnByCVE",
        vulnerability: routeParams.cve,
        teamId: teamIdForApi,
      },
    ],
    ({ queryKey }) => {
      return softwareVulnAPI.getVulnerability(queryKey[0]);
    },
    {
      ...DEFAULT_USE_QUERY_OPTIONS,
      retry: false,
      onError: (error) => {
        if (!ignoreAxiosError(error, [403, 404])) {
          handlePageError(error);
        }
      },
    }
  );

  const onTeamChange = useCallback(
    (teamId: number) => {
      handleTeamChange(teamId);
    },
    [handleTeamChange]
  );

  const renderCards = (v: IVulnerabilityResponse) => (
    <>
      <SoftwareVulnSummary
        vuln={v.vulnerability}
        isPremiumTier={isPremiumTier ?? false}
        teamIdForApi={teamIdForApi}
      />
      {!!v.os_versions && v.os_versions.length > 0 && (
        <SoftwareVulnOSVersions
          osVersions={v.os_versions}
          isPremiumTier={isPremiumTier ?? false}
          router={router}
          teamIdForApi={teamIdForApi}
        />
      )}

      {!!v.software && v.software.length > 0 && (
        <SoftwareVulnSoftwareVersions
          vulnSoftware={v.software}
          isPremiumTier={isPremiumTier ?? false}
          router={router}
          teamIdForApi={teamIdForApi}
        />
      )}
    </>
  );

  const renderContent = () => {
    if (isVulnLoading) {
      return <Spinner />;
    }
    return (
      <>
        {isPremiumTier && !config?.partnerships?.enable_primo && (
          <TeamsHeader
            isOnGlobalTeam={isOnGlobalTeam}
            currentTeamId={currentTeamId}
            userTeams={userTeams}
            onTeamChange={onTeamChange}
          />
        )}
        {isVulnError || !vuln ? (
          <DetailsNoHosts
            header="Vulnerability not detected"
            details={`No hosts are affected by ${routeParams.cve}.`}
          />
        ) : (
          renderCards(vuln)
        )}
      </>
    );
  };

  return (
    <MainContent className={baseClass}>
      <>{renderContent()}</>
    </MainContent>
  );
};

export default SoftwareVulnerabilityDetailsPage;
